﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHCfg = NHibernate.Cfg;
using FluentNHibernate.Cfg;
using YasharEl.Infrastructure.ObjectFactory;
using System.Reflection;
using YasharEl.Infrastructure.Caching.Orm;
using YasharEl.Infrastructure.Caching.NHibernate.Integration;

namespace YasharEl.Infrastructure.PersistenceModel.NHibernate
{
    public abstract class NHibernatePersistenceModelConfigurationBuilder : BasePersistenceModelConfigurationBuilder<NHCfg.Configuration>
    {
        #region Fields

        private NHCfg.Configuration cfg;
        private FluentConfiguration fluentCfg;
        private NHCfg.Configuration buildCfg;

        #endregion

        #region BasePersistenceModelConfigurationBuilder<NHCfg.Configuration> Public Methods Overrides

        public override NHCfg.Configuration GetConfiguration()
        {
            if (buildCfg == null)
            {
                buildCfg = fluentCfg.BuildConfiguration();
            }
            return buildCfg;
        }

        #endregion

        #region BasePersistenceModelConfigurationBuilder<NHCfg.Configuration> Methods Overrides

        protected override void ConfigurateUsingConfigurationFile(string settingsFile)
        {
            cfg = new NHCfg.Configuration();
            if (string.IsNullOrEmpty(settingsFile))
            {
                cfg.Configure();
            }
            else
            {
                cfg.Configure(settingsFile);
            }

            fluentCfg = Fluently.Configure(cfg);
        }

        protected override void ConfigurateConnectionString(string connectionStringName)
        {
        }

        protected override void ConfigurateOrmCacheProvider(IDependencyResolver resolver)
        {
            fluentCfg.Cache
            (
                (c) =>
                {
                    IOrmCacheManager ormCacheManager = null;
                    try
                    {
                        resolver.Resolve<IOrmCacheManager>();
                    }
                    catch
                    {
                        ormCacheManager = null;
                    }
                    if (ormCacheManager != null)
                    {
                        c.UseSecondLevelCache().ProviderClass<NHibernateOrmCacheProvider>();
                    }
                }
            );
        }

        protected override void ConfigurateEntityMappings()
        {
            foreach (Assembly hbmAssembly in EnumerateAssembliesWithHbmMappings())
            {
                fluentCfg.Mappings(m => m.HbmMappings.AddFromAssembly(hbmAssembly));
            }

            foreach (Assembly fluentAssembly in EnumerateAssembliesWithFluentMappings())
            {
                fluentCfg.Mappings(m => m.FluentMappings.AddFromAssembly(fluentAssembly));
            }
        }

        #endregion

        #region Abstract Methods

        protected abstract IEnumerable<Assembly> EnumerateAssembliesWithHbmMappings();
        protected abstract IEnumerable<Assembly> EnumerateAssembliesWithFluentMappings();

        #endregion
    }
}
